package eu.sudparis.it.opp.graph;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import eu.sudparis.it.opp.Node;

public class Modularity<T extends Node> {

	private Snapshot<T> remain;
	private Set<Set<Integer>> groups;
	public Modularity(Snapshot<T> remain, Set<Set<Integer>> group){
		this.remain=remain;
		this.groups=group;
	}
	
	public double calculate(){
		List<Integer> act = new ArrayList<Integer>();
		for (T actor : remain.nodes) {
			act.add(actor.id);
		}
		double[][] matrix = new double[act.size()][act.size()];
		double size = remain.edges.size();
		List<Edge> edges = remain.edges;
		for (Edge edge : remain.edges) {
			if (inSameGroup(edge.nda, edge.ndb)) {
				double value = (1 - degree(edges, edge.nda)
						* degree(edges, edge.ndb) / size)
						/ size;
				matrix[act.indexOf(edge.nda)][act.indexOf(edge.ndb)] = value;
				matrix[act.indexOf(edge.ndb)][act.indexOf(edge.nda)] = value;
			} else {
				matrix[act.indexOf(edge.nda)][act.indexOf(edge.ndb)] = 0;
				matrix[act.indexOf(edge.ndb)][act.indexOf(edge.nda)] = 0;
			}
		}
		double sum = 0;
		for (int i = 0; i < act.size(); i++) {
			for (int j = 0; j < act.size(); j++) {
				sum += matrix[i][j];
			}
		}
		return sum;
	}

	public double degree(List<Edge> edges, int node) {
		int i = 0;
		for (Edge edge : edges) {
			if (edge.nda == node || edge.ndb == node)
				i++;
		}
		return i;
	}

	public boolean inSameGroup(int a, int b) {// the modularity of current
												// groups
		for (Set<Integer> group : groups) {
			if (group.contains(a) && group.contains(b))
				return true;
		}
		return false;
	}
}
